﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Webdiyer.AspNetCore;
using ZhongKeSite.Entity;

namespace ZhongKeSite.Repository
{
    public class Repository<T> : IRepository<T> where T : class
    {
        public readonly ZhongKeContext _dbContext;
        public Repository(ZhongKeContext dbContext)
        {
            _dbContext = dbContext;
        }
        public virtual T GetById(object id)
        {
            return _dbContext.Set<T>().Find(id);
        }
        public virtual T FirstOrDefault()
        {
            return _dbContext.Set<T>().FirstOrDefault();
        }
        public virtual T GetByExpression(Expression<Func<T, bool>> predicate)
        {
            return _dbContext.Set<T>().FirstOrDefault(predicate);
        }
        public virtual IEnumerable<T> GetList()
        {
            return _dbContext.Set<T>().AsEnumerable();
        }
        public virtual IEnumerable<T> GetList(Expression<Func<T, bool>> predicate)
        {
            return _dbContext.Set<T>()
                   .Where(predicate)
                   .AsEnumerable();
        }
        public virtual IQueryable<T> GetQueryable(Expression<Func<T, bool>> predicate)
        {
            return _dbContext.Set<T>()
                   .Where(predicate);
        }
        public virtual int Count(Expression<Func<T, bool>> predicate)
        {
            return _dbContext.Set<T>()
                   .Count(predicate);
        }
        public virtual decimal Sum(Expression<Func<T, bool>> predicate, Expression<Func<T, decimal>> selector)
        {
            return _dbContext.Set<T>()
                   .Where(predicate).Sum(selector);
        }
        public virtual PagedList<T> GetPagedList(int pageIndex, int pageSize, Expression<Func<T, bool>> predicate)
        {
            return _dbContext.Set<T>()
                   .Where(predicate).
                   ToPagedList<T>(pageIndex, pageSize);
        }

        public bool Add(T entity)
        {
            _dbContext.Set<T>().Add(entity);
            return _dbContext.SaveChanges() > 0;
        }
        public async Task<bool> AddTask(T entity)
        {
            _dbContext.Set<T>().Add(entity);
            return await _dbContext.SaveChangesAsync() > 0;
        }

        public bool Add(List<T> entitys)
        {
            _dbContext.Set<T>().AddRange(entitys);
            return _dbContext.SaveChanges() > 0;
        }
        public bool Update(T entity)
        {
            _dbContext.Set<T>().Attach(entity);
            _dbContext.Entry(entity).State = EntityState.Modified;
            return _dbContext.SaveChanges() > 0;
        }
        public bool Update(List<T> entitys)
        {
            _dbContext.Set<T>().AttachRange(entitys);
            entitys.ForEach(entity =>
            {
                _dbContext.Entry(entity).State = EntityState.Modified;
            });
            return _dbContext.SaveChanges() > 0;
        }
        public bool Delete(T entity)
        {
            _dbContext.Set<T>().Remove(entity);
            _dbContext.SaveChanges();
            return true;
        }
        public bool Delete(List<T> entitys)
        {
            _dbContext.Set<T>().RemoveRange(entitys);
            _dbContext.SaveChanges();
            return true;
        }
        public bool Delete(string id)
        {
            var entity = _dbContext.Set<T>().Find(id);
            if (entity != null)
            {
                _dbContext.Set<T>().Remove(entity);
                _dbContext.SaveChanges();
            }
            return true;
        }
        public bool Delete(Expression<Func<T, bool>> predicate)
        {
            var entitys = _dbContext.Set<T>().Where(predicate).ToList();
            if (entitys != null && entitys.Count > 0)
            {
                _dbContext.Set<T>().RemoveRange(entitys);
                _dbContext.SaveChanges();
            }
            return true;
        }

        public bool Execute(string sql)
        {
            RawSqlString rawSqlString = new RawSqlString(sql);
            return _dbContext.Database.ExecuteSqlCommand(rawSqlString) > 0;
        }

        public bool Execute(string sql, params object[] paras)
        {
            RawSqlString rawSqlString = new RawSqlString(sql);
            return _dbContext.Database.ExecuteSqlCommand(rawSqlString, paras) > 0;
        }

        public bool Execute(string sql, IEnumerable<object> paras)
        {
            RawSqlString rawSqlString = new RawSqlString(sql);
            return _dbContext.Database.ExecuteSqlCommand(rawSqlString, paras) > 0;
        }
    }
}
